package com.tnovoselec.server.travelassistant.worker;

import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.tnovoselec.server.travelassistant.Config;
import com.tnovoselec.server.travelassistant.beans.City;
import com.tnovoselec.server.travelassistant.util.Util;
import com.tnovoselec.server.travelassistant.util.XMLUtil;

public class WeatherParser implements IParser {

	private Map<String, String> conditions;
	private Map<String, String> backgrounds;
	private Map<String, City> cities;
	private List<String> locations;
	private Document document = null;

	@Override
	public void parse() {
		parseBackgrounds();
		parseConditions();
		parseLocations();
		parseWeather();
	}

	@Override
	public Document getDoc() {
		return document;
	}

	private void parseBackgrounds() {
		try {
			Document document = XMLUtil.getDoc(Util.getBytesFrom(new FileInputStream(new File(Config.backgroundsXML)),
					true));
			backgrounds = new HashMap<String, String>();
			NodeList backgroundTypes = document.getDocumentElement().getElementsByTagName("type");
			for (int i = 0; i < backgroundTypes.getLength(); i++) {
				backgrounds.put(backgroundTypes.item(i).getTextContent().toLowerCase(),
						XMLUtil.getNodeAttribute(backgroundTypes.item(i), "url"));
			}
		} catch (Exception ex) {
			String s = ex.getMessage();
			System.out.println(s);

		}
	}

	private void parseConditions() {
		try {
			Document document = XMLUtil.getDoc(Util.getBytesFrom(new FileInputStream(new File(Config.conditionsXML)),
					true));
			conditions = new HashMap<String, String>();
			NodeList conditionTypes = document.getDocumentElement().getElementsByTagName("type");
			for (int i = 0; i < conditionTypes.getLength(); i++) {
				conditions.put(conditionTypes.item(i).getTextContent().toLowerCase(),
						XMLUtil.getNodeAttribute(conditionTypes.item(i), "url"));
			}
		} catch (Exception ex) {
			String s = ex.getMessage();
			System.out.println(s);
		}
	}

	private void parseLocations() {
		locations = new ArrayList<String>();
		cities = new HashMap<String, City>();
		try {
			Document document = XMLUtil.getDoc(Util.getBytesFrom(new FileInputStream(new File(Config.locationsXML)),
					true));

			NodeList locs = document.getDocumentElement().getElementsByTagName("city");
			City city;
			for (int i = 0; i < locs.getLength(); i++) {
				city = new City();
				city.setName(locs.item(i).getTextContent());
				city.setLat(locs.item(i).getAttributes().getNamedItem("lat").getTextContent());
				city.setLng(locs.item(i).getAttributes().getNamedItem("lng").getTextContent());
				locations.add(locs.item(i).getTextContent().toLowerCase());
				cities.put(locs.item(i).getTextContent().toLowerCase(), city);
			}
		} catch (Exception ex) {
			String s = ex.getMessage();
			System.out.println(s);
		}
	}

	private void parseWeather() {
		Element root = null;
		try {
			document = XMLUtil.getEmptyDoc();
			root = XMLUtil.createElement(document, "items", null);
		} catch (Exception e) {
			// TODO: handle exception
		}
		int i = 0;
		for (String city : locations) {
			try {
				if (city == null) {
					continue;
				}
				Element cityElement = XMLUtil.createElement(document, "item", root);
				XMLUtil.createElement(document, "id", String.valueOf(i), cityElement);
				XMLUtil.createElement(document, "lat", cities.get(city).getLat(), cityElement);
				XMLUtil.createElement(document, "lng", cities.get(city).getLng(), cityElement);
				XMLUtil.createElement(document, "title", cities.get(city).getName(), cityElement);
				// XMLUtil.createElement(document, "url", Config.externalURL +
				// escapeManual(city).toLowerCase().replace(" ", ""),
				// cityElement);

				// request = new HTTPRequest(new URL(Config.apiUrl + "?weather="
				// + URLEncoder.encode(escapeManual(city).toLowerCase()) +
				// "&hl=" + "en-GB"));
				// URL url = new URL(Config.newApiUrl +
				// URLEncoder.encode(Util.escapeManual(city).toLowerCase())));
				HttpClient httpclient = new DefaultHttpClient();
				HttpGet httpget = new HttpGet(Config.newApiUrl
						+ URLEncoder.encode(Util.escapeManual(city).toLowerCase())+ ",croatia");
				ResponseHandler<String> responseHandler = new BasicResponseHandler();
				String responseBody = httpclient.execute(httpget, responseHandler);
				
				byte[] data = responseBody.getBytes();
				String temp = new String(data, "UTF-8");
				Document doc = XMLUtil.getDoc(temp.getBytes());

				doc = parseXML(doc, city);
				Node imported = document.importNode(doc.getDocumentElement(), true);
				cityElement.appendChild(imported);

				//GoogleWeatherServlet.CACHE.put(escapeManual(city).toLowerCase().replace(" ", ""), new DOMSource(doc));
				i++;
			} catch (Exception e) {
			//	log.info(e.getMessage());
				System.out.println(e.getMessage());
			}
		}
		document.appendChild(root);
	}
	private Document parseXML(Document document, String location) {
		System.out.println(location);
		try {
			if (Util.isEmpty(conditions) || conditions.size() < 1) {
				// throw new
				// AdapterException("No conditions found! Aborting parser.");
			}

			// Document document = XMLUtil.getDoc(dataSource.getInputStream());
			Document doc = XMLUtil.getEmptyDoc();
			Node root = XMLUtil.createElement(doc, "weathers", null);

			Node currentCondition = document.getDocumentElement().getElementsByTagName("current_condition").item(0);
			//int condition = 0;
			String backgroundUrl = "";
			String iconUrl = "";
			String windSpeed = "";
			String windDirection = "";
			String windUnit = "";
			for (Node n : XMLUtil.getChildNodes(currentCondition)) {
				if (n.getNodeName().equals("weatherDesc")) {
					XMLUtil.addAttirbute((Element) n, "data", n.getTextContent().trim());
					//condition = 0;
					// backgroundUrl =
					// backgrounds.get(n.getTextContent().toLowerCase());
					// iconUrl =
					// conditions.get(n.getTextContent().toLowerCase());
				} else if (n.getNodeName().equals("temp_F")) {
					n.getParentNode().removeChild(n);
				} else if (n.getNodeName().equals("temp_C")) {
					XMLUtil.addAttirbute((Element) n, "data", n.getTextContent().trim());
				} else if (n.getNodeName().equals("humidity")) {
					XMLUtil.addAttirbute((Element) n, "data", n.getTextContent());
				} else if (n.getNodeName().equals("weatherIconUrl")) {
					n.getParentNode().removeChild(n);
				} else if (n.getNodeName().equals("windspeedKmph")) {
					windSpeed = n.getTextContent();
				} else if (n.getNodeName().equals("winddir16Point")) {
					windDirection = n.getTextContent();
				} else if (n.getNodeName().equals("weatherCode")) {
					XMLUtil.addAttirbute((Element) n, "data", n.getTextContent());
					iconUrl = conditions.get(n.getTextContent().toLowerCase());
					backgroundUrl = backgrounds.get(n.getTextContent().toLowerCase());
				}
			}

			Element ewDirection = XMLUtil.createElement(document, "wind_direction", (Element) currentCondition);
			XMLUtil.addAttirbute(ewDirection, "data", windDirection);
			currentCondition.appendChild(ewDirection);
			Element ewSpeed = XMLUtil.createElement(document, "wind_speed", (Element) currentCondition);
			XMLUtil.addAttirbute(ewSpeed, "data", windSpeed);
			XMLUtil.addAttirbute(ewSpeed, "unit", "km/h");
			currentCondition.appendChild(ewSpeed);
			Element backgroundUrlElement = XMLUtil.createElement(document, "background", (Element) currentCondition);
			Element iconEl = XMLUtil.createElement(document, "icon", (Element) currentCondition);
			XMLUtil.addAttirbute(iconEl, "data", iconUrl);
			XMLUtil.addAttirbute(backgroundUrlElement, "data", backgroundUrl);

			Node cond = doc.importNode(currentCondition, true);
			root.appendChild(cond);

			NodeList conds = document.getDocumentElement().getElementsByTagName("weather");
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Calendar c = Calendar.getInstance();
			for (int i = 0; i < conds.getLength(); i++) {
				//Node icon = null;
				for (Node n : XMLUtil.getChildNodes(conds.item(i))) {
					if (n.getNodeName().equals("weatherIconUrl")) {
						//icon = n;
					} else if (n.getNodeName().equals("weatherDesc")) {
						XMLUtil.addAttirbute((Element) n, "data", n.getTextContent().trim());
						// Element iconE = XMLUtil.createElement(document,
						// "icon", (Element) conds.item(i));
						// XMLUtil.addAttirbute(iconE, "data",
						// conditions.get(n.getTextContent().toLowerCase()));
						// icon.getAttributes().getNamedItem("data")
						// .setTextContent(conditions.get(n.getAttributes().getNamedItem("data").getTextContent().toLowerCase()));
					} else if (n.getNodeName().equals("date")) {
						Element date = XMLUtil.createElement(document, "day_of_week", (Element) conds.item(i));
						String dateS = n.getTextContent();

						Date d = sdf.parse(dateS);

						c.setTime(d);
						XMLUtil.addAttirbute(date, "data", "" + c.get(Calendar.DAY_OF_WEEK));
					} else if (n.getNodeName().equals("tempMaxC")) {
						XMLUtil.addAttirbute((Element) n, "data", n.getTextContent());
					} else if (n.getNodeName().equals("tempMinC")) {
						XMLUtil.addAttirbute((Element) n, "data", n.getTextContent());
					} else if (n.getNodeName().equals("weatherCode")) {
						XMLUtil.addAttirbute((Element) n, "data", n.getTextContent());
						Element iconE = XMLUtil.createElement(document, "icon", (Element) conds.item(i));
						XMLUtil.addAttirbute(iconE, "data", conditions.get(n.getTextContent().toLowerCase()));
					}
				}
				Node fcond = doc.importNode(conds.item(i), true);
				root.appendChild(fcond);
			}

			doc.appendChild(root);
			return (doc);
		} catch (Exception ex) {
			
			ex.printStackTrace();
		}
		return null;
	}

	@Override
	public String getXMLName() {
		return Config.METEO_XML_NAME;
	}
}
